namespace KillerKitty {
	
	using namespace std;
	
	//Logger class
	//handles all logging
	class kkLogger : public KillerKittyBase{

	private:
		ofstream *outputStream;
		string logFile;
		bool bLoggingEnabled;
		bool bLoggingCompletelyDisabled;	//used in rare cases, if err occurs eg. if fileopen failed etc
		logLevel_e curLogLevel;

		static int cntInstances;

	public:
		kkLogger();
		kkLogger( string& fName );
		~kkLogger();
		
		//should be self explanatory
		void inline  logDiable(){ bLoggingEnabled = false; };
		//returns whether enbling was successful
		bool inline logEnable(){ bLoggingEnabled = !bLoggingCompletelyDisabled; return bLoggingEnabled; };
		void setLogLevel(logLevel_e logLevel) { curLogLevel = logLevel; }	//FIXME:validate
		//loglevel is the maximum loglevel at which message will be diplayed. (ie current log level must be atleast equal to or lesser than this)
		void write(KillerKittyBase *src, string message, logLevel_e logLevel);


	};
	int kkLogger::cntInstances = 0;

	kkLogger::kkLogger() {
	
		bLoggingEnabled = true;
		curLogLevel = debug;

		//FIXME:poor way to ensure that only one instance is used. automatically disables any new instance.
		if((++cntInstances)!=1) bLoggingCompletelyDisabled=true;

		outputStream = new ofstream(DEFAULT_LOGFILE);
		if( !outputStream->is_open() ) { 	//if file open fails
			cerr<<"Error opening logfile "<<DEFAULT_LOGFILE<<"!"<<endl;
			//FIXME:possibly redirect output somewhere else.
			bLoggingCompletelyDisabled=true;
			bLoggingEnabled=false;
		}
	}

	kkLogger::kkLogger(string& fName) {
		bLoggingEnabled =true;
		curLogLevel = debug;

		if((++cntInstances)!=1) bLoggingCompletelyDisabled=true;

		outputStream = new ofstream( fName.data() );

		if( !outputStream->is_open() ) {	//if file open fails
			outputStream = new ofstream(DEFAULT_LOGFILE);	//try opening default log file
			if( !outputStream->is_open() ) {	
				(*outputStream)<<"Error opening "<<fName<<". Opened "<<DEFAULT_LOGFILE<<" instead."<<endl;
			}
			else { //if that fails also print error and forget
				cerr<<"Error opening logfile "<<fName<<" and "<<DEFAULT_LOGFILE<<"!"<<endl;
				bLoggingCompletelyDisabled=true;
				bLoggingEnabled=false;

			}
		}
		
		
	}

	kkLogger::~kkLogger() {

		outputStream->close();
		delete outputStream;
	}

	void kkLogger::write(KillerKittyBase *src, string message, KillerKitty::logLevel_e logLevel) {

		if(bLoggingEnabled==false || curLogLevel > logLevel || bLoggingCompletelyDisabled==true ) return;

		//TODO: Replace all time functions with those provided by boost

		//get current date and time
		//FIXME:check ret val
		char timebuf[128];
		_strtime_s(timebuf,128);
		string sTime(timebuf);
		_strdate_s(timebuf,128);
		string sDate(timebuf);
		try {
			if(src!=NULL) {
				//search in reverse for : and print from the next character to get class name.
				(*outputStream)<<sDate<<" "<<sTime<<" : "<<(strrchr(typeid(*src).name(),':')+1)<<" : "<<message<<endl;
				cout<<sDate<<" "<<sTime<<" : "<<(strrchr(typeid(*src).name(),':')+1)<<" : "<<message<<endl;
			}
			else {
				(*outputStream)<<sDate<<" "<<sTime<<" : "<<"Undefined Source"<<" : "<<message<<endl;
				cout<<sDate<<" "<<sTime<<" : "<<"Undefined Source"<<" : "<<message<<endl;
			}
			(*outputStream).flush();	//shouldnt affect performance, since theoretically, log.write shouldnt be called that often...
		}
		catch (int ex) {
			cerr<<"Error writing to log! error code : "<<ex<<endl;
		}
	}

};